<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/3/20
 * Time: 14:06
 */

namespace app\api\Service;
use app\api\library\enum\BanktypeEnum;
use app\common\library\Auth;
use fast\Http;
use think\Config;
use think\Db;
use app\common\model\WalletLog;
use app\common\model\WalletRecord;
use app\common\model\Wallet as WalletModel;
use think\Queue;
use app\common\model\WallertMultiple;

class WalletService
{
    public $auth;
    protected $type;        //交易类型
    protected $remark;      //备注
    protected $banktype;    //银行卡类型
    protected $paychannel; //支付渠道

    public function __construct()
    {
        $this->auth = Auth::instance();
    }

    /**
     * 提现操作
     * @param $money
     * @return array
     */
    public static function tixian($money)
    {
        $user_id = Auth::instance()->id;
        $now = time();
        Db::startTrans();
        try{
            WalletModel::where('user_id',$user_id)->update([
                'money'     => Db::raw('money-'.$money),
                'lock_money'=>  Auth::instance()->group_id == 1 ? 0 : Db::raw('lock_money+'.$money),
                'extract_num'=> Db::raw('extract_num-1')
            ]);
            $record_sn = checkRecordSn();
            WalletRecord::insert([
                'record_sn' => $record_sn,
                'user_id'   => $user_id,
                'type'      => 2,    //中奖上分
                'money'     => $money,
                'remark'    => '提现',
                'pay_status'=> Auth::instance()->group_id == 1 ? 1 : 0,
                'pay_time'  => $now,
                'createtime'=> $now,
            ]);
            WalletLog::insert([
                'record_sn' => $record_sn,
                'user_id'   => $user_id,
                'change_money'=> '-'.$money,
                'money'     => WalletModel::where('user_id',$user_id)->value('money'),
                'remark'    => '提现',
                'createtime'=> $now,
            ]);
            Db::commit();
            return ['code'=>200,'msg'=>'success'];
        }catch (Exception $e){
            file_put_contents(
                WALLET_ERROR_PATH,
                '【' . date( 'Y-m-d H:i:s', $_SERVER[ 'REQUEST_TIME' ] ) . '】  钱包用户上分异常'.json_encode($e->getMessage()). PHP_EOL,
                FILE_APPEND
            );
            Db::rollback();
            return ['code'=>301,'msg'=>$e->getMessage()];
        }
    }

    /**
     * wallet 相关操作
     * @param $money
     * @param $user_id
     * @param $type
     * @param $remark
     * @param int $pay_status
     * @return string 订单号
     * @throws \Complex\Exception
     */
    public function saveWallet($money,$user_id,$type,$remark,$pay_status = 0,$index = '')
    {
        $now = time();
        if( $money < 0 ){
            $data = [
                'money'     => Db::raw('money'.$money),
            ];
        }else{
            $data = [
                'money'     => Db::raw('money+'.$money),
            ];
        }
        WalletModel::where('user_id',$user_id)->update($data);
        $record_sn = checkRecordSn();
        WalletRecord::insert([
            'record_sn' => $record_sn,
            'user_id'   => $user_id,
            'type'      => $type,
            'money'     => \Complex\abs($money),
            'remark'    => $remark,
            'pay_status'=> $pay_status,
            'pay_time'  => $now,
            'createtime'=> $now,
            'index'     => $index
        ]);
        if( $money > 0 ){
            $change_money = '+'.$money;
        }else{
            $change_money = $money;
        }
        WalletLog::insert([
            'record_sn'     => $record_sn,
            'user_id'       => $user_id,
            'change_money'  => $change_money,
            'money'         => WalletModel::where('user_id',$user_id)->value('money'),
            'remark'        => $remark,
            'createtime'    => $now,
            'index'         => $index
        ]);
        return $record_sn;
    }

    /**
     * 记录流水-只针对下注
     * @param $user_id
     * @param $remark
     * @param $record_sn
     * @param $change_money
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function recordWaterMultiple($user_id,$remark,$record_sn,$change_money)
    {
        $waterMultiple = new WallertMultiple();
        $lastwater = $waterMultiple::where('user_id',$user_id)
            //->where('surpluswate','>=',0)
            ->order('id','desc')->limit(1)->field('surpluswate,beallwate')->find();//记录流水
        $surplusum = $lastwater ? $lastwater['surpluswate'] : 0;
        $beallwate = $lastwater ? $lastwater['beallwate'] : 0;
        $waterMultipleData = [
            'remark'    => $remark,
            'record_sn' => $record_sn,
            'change_money' => '-'.$change_money,
            'beallwate' => $beallwate,
            'surpluswate'=> $surplusum - $change_money,
            'user_id'   => $this->auth->id,
            'type'      => 3
        ];
        $waterMultiple->data($waterMultipleData)->save();
    }

    /**
     * @param $user_id  int 用户ID
     * @param $money    string 充值金额
     * @param $type     int
     * @param string $banktype
     * @return array
     * @throws \Complex\Exception
     */
    public function recharge($user_id,$money,$type,$banktype = '')
    {
        if( empty($user_id) ){
            return ['code'=>301,'msg'=>'当前用户不存在！'];
        }
        if( empty($money) ){
            return ['code'=>303,'msg'=>'请输入正确金额'];
        }
        $now = time();
        $ismobile = isMobile();
        if( $type == 'wechat' ){
            $this->type = 1;
            $this->remark = '微信充值';
            if( $ismobile ){ //手机/pc都使用扫码支付
                $this->banktype = BanktypeEnum::WECHARTQRCODE;
            }else{
                $this->banktype = BanktypeEnum::WECHARTQRCODE;
            }
            $this->paychannel = 'gateway';
        }
        if( $type == 'alipay' ){
            $this->type = 3;
            $this->remark = '支付宝充值';
            if( $ismobile ){ //手机使用支付宝直连，pc使用扫码通道
                $this->banktype = BanktypeEnum::ALIPAYH5;
            }else{
                $this->banktype = BanktypeEnum::ALIPAYQRCODE;
            }
            $this->paychannel = 'gateway';
        }
        if( $type == 'unionpay' ){
            $this->type = 7;
            $this->remark = '银行转账';
            $this->banktype = $banktype;
            $this->paychannel = 'fastpay';
        }
        $orderid = $this->makeOrderNo();
        //----创建订单start----
        Db::startTrans();
        try{
            WalletRecord::insert([
                'record_sn' => $orderid,
                'user_id'   => $user_id,
                'type'      => $this->type,
                'money'     => \Complex\abs($money),
                'remark'    => $this->remark,
                'pay_status'=> 0,
                'pay_time'  => 0,
                'createtime'=> $now
            ]);
            if( $money > 0 ){
                $change_money = '+'.$money;
            }else{
                $change_money = $money;
            }
            WalletLog::insert([
                'record_sn' => $orderid,
                'user_id'   => $user_id,
                'change_money'=> $change_money,
                'money'     => WalletModel::where('user_id',$user_id)->value('money'),
                'remark'    => $this->remark,
                'createtime'=> $now
            ]);
            Db::commit();
        }catch (Exception $e){
            file_put_contents(
                WALLET_ERROR_PATH,
                '【' . date( 'Y-m-d H:i:s', $_SERVER[ 'REQUEST_TIME' ] ) . '】  用户{'.$user_id.'}创建订单失败'.json_encode($e->getMessage()). PHP_EOL,
                FILE_APPEND
            );
            Db::rollback();
            return ['code'=>302,'msg'=>'创建订单失败'];
        }
        $jobHandlerClassName = 'app\api\job\HandlePay';
        $jobQueueName = 'handlepay';
        Queue::push($jobHandlerClassName,['record_sn'=>$orderid],$jobQueueName);
        //----创建订单end----
        if( $this->paychannel == 'gateway' ){
            $res= $this->_gateway($money,$orderid);
            $res = json_decode($res,true);
        }elseif( $this->paychannel == 'fastpay' ){
            $res = $this->_fastPay($money,$orderid);
            return $res;
        }else{
            return ['code'=>305,'msg'=>'支付通道错误！'];
        }

        if( $res['code'] == 1 ) { //支付失败
            WalletRecord::where('record_sn',$orderid)->update([
                'pay_status'    => -1,//修改支付结果
                'pay_time'      => time()
            ]);
            return [
                'code'  => 304,
                'msg'   => $res['msg']
            ];
        }
        if( $res['code'] == 0 ){
            if( $type == 'wechat' ){ //如果是微信支付返回二维码
                if( $money >= 500 ){
                    return [
                        'code'  => 200,
                        'isqr'  => 0,
                        'qrinfo'=> '',
                        'url'   => $res['qrinfo']
                    ];
                }else{
                    $imageService = ImageService::getInstance();
                    $filename = $imageService->createQRcode('./qrcode/',$res['qrinfo'],'L',8,'wechat');
                    return [
                        'code'  => 200,
                        'isqr'  => 1,
                        'qrinfo'=> '/qrcode/'.$filename,
                        'url'   => ''
                    ];
                }
            }
            if( $type == 'alipay' ){
                return [
                    'code'  => 200,
                    'isqr'  => 0,
                    'qrinfo'=> '',
                    'url'   => $res['qrinfo']
                ];
            }
        }
    }

    //创建订单
    public function makeOrderNo()
    {
        $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
        $orderSn =
            $yCode[intval(date('Y')) - 2017] . strtoupper(dechex(date('m'))) . date(
                'd') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf(
                '%02d', rand(0, 99));
        $count = WalletRecord::where('record_sn',$orderSn)->count();
        if( $count > 1 ){
            $this->makeOrderNo();
        }else{
            return $orderSn;
        }
    }

    /**
     * 快捷支付通道
     * @param $money    string 支付金额
     * @param $orderid  string 订单号
     * @return mixed|string
     */
    private function _gateway($money,$orderid)
    {
        $customer = Config::get('pay.customer');
        $banktype = $this->banktype;
        $amount   = sprintf("%.2f",$money);
        $asynbackurl = Config::get('pay.asynbackurl');
        $request_time = date('YmdHis',time());
        $key = Config::get('pay.key');
        $url = Config::get('pay.gatewayurl');
        $signstr = "customer={$customer}&banktype={$banktype}&amount={$amount}&orderid={$orderid}&asynbackurl={$asynbackurl}&request_time={$request_time}&key={$key}";
        $data = [
            'customer'  => $customer,
            'banktype'  => $banktype,
            'amount'    => $amount,
            'orderid'   => $orderid,
            'asynbackurl'=> $asynbackurl,
            'request_time'=> $request_time,
            'israndom'  => Config::get('pay.israndom'),
            'isqrcode'  => 'Y',
            'sign'      => md5($signstr)
        ];
        return Http::post($url,$data);

    }
    private function _fastPay($money,$orderid)
    {
        $customer = Config::get('pay.customer');
        $amount   = sprintf("%.2f",$money);
        $orderid  = $this->makeOrderNo();
        $asynbackurl = Config::get('pay.asynbackurl');
        $request_time = date('YmdHis',time());
        $url      = Config::get('pay.fastpayurl');
        $key      = Config::get('pay.key');
        $signstr  = "customer={$customer}&amount={$amount}&orderid={$orderid}&asynbackurl={$asynbackurl}&request_time={$request_time}&key={$key}";
        $data = [
            'customer'  => $customer,
            'bankcode'  => $this->banktype,
            'amount'    => $amount,
            'orderid'   => $orderid,
            'asynbackurl'=> $asynbackurl,
            'synbackurl'=>Config::get('pay.synbackurl'),
            'request_time'=> $request_time,
            'israndom'  => Config::get('pay.israndom'),
            'sign'      => md5($signstr)
        ];
        return ['data'=>$data,'url'=>$url];

    }
}